<?php

namespace App\Admin\Eloquent;

use Cache;
use DB;
use CreateActivateMember;
use QueryIsSetPayPassword;

class User extends Model
{
    const ROLES_FOR_USER_CACHED_KEYS = 'roles_for_user';

    const DEFAULT_CACHE_MINUTES = 30;

    const USER_SCOPE_ADMINISTOR = 'administor';

    protected $validatorRules = [
        'username' => 'max:50|unique:users,username,<id>',
        'password' => 'required|min:6|max:60',
    ];

    /**
     * 实例化模型时, 可批量赋值属性白名单
     *
     * @var array
     */
    protected $fillable = [
        'username', 'password', 'email', 'phone_number', 'identity_id', 'phone_number_verified', 'email_verified','last_invest_at','scope'
    ];

    /**
     * 转换成 json 格式时, 过滤的属性
     *
     * @var array
     */
    protected $hidden = [
        'password',
    ];

    public function delete()
    {
        if ($this->isSuperAdministor()) {
            abort(500, '系统超级管理员不允许删除');
        }

        return parent::delete();
    }

    /**
     * 根据凭证检索用户
     *
     * @param  array $credentials
     * @return \App\Admin\Eloquent\User|null
     */
    public static function retrieveByCredentials(array $credentials)
    {
        $query = static::query();

        foreach ($credentials as $key => $value) {
            if (!str_contains('password', $key)) {
                $query->administors()->where($key, $value);
            }
        }

        return $query->first();
    }

    /**
     * 当前用户的所有角色
     */
    public function roles()
    {
        return $this->belongsToMany('App\Admin\Eloquent\Role', 'role_user', 'user_id', 'role_id');
    }

    /**
     * 获取缓存的角色菜单
     *
     * @return \App\Admin\Eloquent\Role[]
     */
    public function cachedRoles()
    {
        $cacheKey = $this->{$this->primaryKey};

        $cachedKeys = Cache::get(self::ROLES_FOR_USER_CACHED_KEYS, function () {
            return [];
        });

        if (!in_array($cacheKey, $cachedKeys)) {
            $cachedKeys[] = $cacheKey;

            Cache::put(self::ROLES_FOR_USER_CACHED_KEYS, $cachedKeys, self::DEFAULT_CACHE_MINUTES);
        }

        return Cache::remember(self::ROLES_FOR_USER_CACHED_KEYS . '_' . $cacheKey, self::DEFAULT_CACHE_MINUTES, function () {
            return $this->roles()->get();
        });
    }

    /**
     * 校验用户权限
     *
     * @param  array|mixed $name
     * @param  bool $requiredAll
     * @return bool
     */
    public function can($name, $requiredAll = false)
    {
        return $this->hasPermission($name, $requiredAll);
    }

    /**
     * 校验用户权限
     *
     * @param  array|mixed $name
     * @param  bool $requiredAll
     * @return bool
     */
    public function cannot($name, $requiredAll = false)
    {
        return !$this->can($name, $requiredAll);
    }

    /**
     * 校验用户权限
     *
     * @param  array|mixed $name
     * @param  bool $requiredAll
     * @return bool
     */
    public function hasPermission($name, $requiredAll = false)
    {
        if (is_array($name)) {
            foreach ($name as $permssionName) {
                $hasPermission = $this->hasPermission($permssionName);

                if (!$requiredAll && $hasPermission) {
                    return true;
                } elseif ($requiredAll && !$hasPermission) {
                    return false;
                }
            }

            return $requiredAll;
        } else {
            foreach ($this->cachedRoles() as $role) {
                if ($role->hasPermission($name)) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * 清空所有的角色缓存
     *
     * @return void
     */
    public static function cleanCachedRoles()
    {
        if (Cache::has(self::ROLES_FOR_USER_CACHED_KEYS)) {
            $cacheKeys = Cache::get(self::ROLES_FOR_USER_CACHED_KEYS, function () {
                return [];
            });

            foreach ($cacheKeys as $cacheKey) {
                Cache::forget(self::ROLES_FOR_USER_CACHED_KEYS . '_' . $cacheKey);
            }

            Cache::forget(self::ROLES_FOR_USER_CACHED_KEYS);
        }
    }

    /**
     * 渲染菜单 html 代码
     *
     * @return string
     */
    public function renderMenus()
    {
        $menus = collect();
        $active='';
        foreach ($this->cachedRoles() as $role) {
            $menus = $menus->merge($role->menus());
            if(empty($active)){$active=$role->getActiveMenus();}
        }
        view()->share("active_menus",$active);
        return $this->renderMenusTmpl($menus->unique(),$active, true);
    }

    /**
     * 获取关联的用户信息
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
     */
    public function userInfo()
    {
        return $this->hasOne('App\Admin\Eloquent\UserInfo');
    }

    /**
     * 获取关联的机构用户信息
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
     */
    public function organizationalInfo()
    {
        return $this->hasOne('App\Admin\Eloquent\OrganizationalUser');
    }

    /**
     * 范围查询只包括系统管理员
     *
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeAdministors($query)
    {
        return $query->where('scope', 'administor');
    }

    /**
     * 范围查询只包括前台用户
     *
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeFronts($query)
    {
        return $query->where('scope', 'front');
    }

    public static function paging_query(array $args, int $pagesize = 15)
    {
        $query = User::fronts()
            ->rightJoin('user_info as a', 'a.user_id', '=', 'users.id');

        //账户激活状态
        if ((!empty($args['is_set_pay_password'])) || $args['is_set_pay_password'] === '0')
            $query = $query->where('a.is_set_pay_password', $args['is_set_pay_password']);

        //姓名 用户名 手机 邮箱 多条件联合查询
        if(!empty($args['userKey']))
            $query = $query->where(function($querys) use ($args){
                $querys->orWhere('users.username', 'like', '%'.$args['userKey'].'%');
                $querys->orWhere('users.phone_number', 'like', '%'.$args['userKey'].'%');
                $querys->orWhere('users.email', 'like', '%'.$args['userKey'].'%');
                $querys->orWhere('a.name', 'like', '%'.$args['userKey'].'%');
            });

        //身份证号码模糊查询
        if(!empty($args['id_card']))
            $query = $query->where('a.id_card', 'like', '%'.$args['id_card'].'%');

        //是否绑定手机号码
        if(!empty($args['is_set_phone']) || $args['is_set_phone'] === '0')
            $query = $query->where('users.phone_number_verified', $args['is_set_phone']);

        //是否绑定银行卡
        if(!empty($args['is_set_bankcard']) || $args['is_set_bankcard'] === '0')
            if($args['is_set_bankcard'] === '0'){
                $query = $query->where(function($querys) use ($args){
                    $querys->whereNull('a.bank_card_number')->orWhere('a.bank_card_number','');
                });
            }else{
                $query = $query->where(function($querys) use ($args){
                    $querys->whereNotNull('a.bank_card_number')->where('a.bank_card_number', '<>' ,'');
                });
            }

        //设置支付密码开始时间
        if(!empty($args['p_start_at']))
            $query->where('a.set_pay_password_time', '>=', $args['p_start_at']);

        //设置支付密码结束时间
        if(!empty($args['p_end_at']))
            $query->where('a.set_pay_password_time', '<=', $args['p_end_at']);

        //注册开始时间
        if(!empty($args['reg_start_at']))
            $query->where('a.set_pay_password_time', '>=', $args['reg_start_at']);

        //注册结束时间
        if(!empty($args['reg_end_at']))
            $query->where('a.set_pay_password_time', '<=', $args['reg_end_at']);

        
        //Excel 下载
         if($args['download'] == 'download'){
            $data = $query->orderBy('users.created_at','desc')->get();
            qeury_export_excel('用户管理',$data);
        }


        return $query->orderBy('users.created_at','desc')->paginate($pagesize);
    }
    /**
     *  查询用户记录 
     *  
     * @param  array       $args     [description]
     * @param  int|integer $pagesize [description]
     * @return [type]                [description]
     */
    public static function paginteQueryOrganizational(array $args, int $pagesize = 15)
    {
        $query = User::fronts()
            ->rightJoin('organizational_users as a', 'a.user_id', '=', 'users.id');

        //追加查询条件
        if (!empty($args['username']))
            $query = $query->where('users.username', 'like', '%' . $args['username'] . '%');

        if (!empty($args['company_name']))
            $query = $query->where('a.company_name', 'like', '%' . $args['company_name'] . '%');

        if (!empty($args['status']))
            $query = $query->where('a.status', 'like', '%' . $args['status'] . '%');

        if(!empty($args['org_code']))
            $query = $query->where('a.code',$args['org_code']);

        return $query->paginate($pagesize);
    }
    /**
     * 查询管理员记录
     * @param  array       $args     [description]
     * @param  int|integer $pagesize [description]
     * @return [type]                [description]
     */
    public static function paginateQueryAdministor(array $args, int $pagesize = 15)
    {
        $query = User::administors()
            ->leftJoin('user_info as a', 'a.user_id', '=', 'users.id');

        //追加查询条件
        if (!empty($args['username']))
            $query = $query->where('users.username', 'like', '%' . $args['username'] . '%');

        if (!empty($args['name']))
            $query = $query->where('a.name', 'like', '%' . $args['name'] . '%');

        if (!empty($args['id_card']))
            $query = $query->where('a.id_card', 'like', '%' . $args['id_card'] . '%');

        if (!empty($args['phone']))
            $query = $query->where('a.phone', 'like', '%' . $args['phone'] . '%');

        return $query->paginate($pagesize);
    }

    /**
     * 渲染菜单模板
     *
     * @param  \Illuminate\Support\Collection
     * @param  bool $top
     * @return string
     */
    protected function renderMenusTmpl($menus, $active,$top = false)
    {
        $html = '';
        foreach ($menus as $menu) {
            $str='';
            if(! $active->where('id', $menu->id)->isEmpty()){
                $str='active';
            }

            $html .= '<li class="'.$str.'"><a href="'. (!empty($menu->uri) ? url($menu->uri) : '#').'">'.$menu->name;
            if (!$menu->childrenMenus->isEmpty()) {
                $html .= '<span class="fa new-arrow"></span></a>';
                $html .= $this->renderMenusTmpl($menu->childrenMenus,$active,false);
            } else {
                $html .= '</a>';
            }

            $html .= '</li>';
        }

        if ($top) {
            return sprintf('<ul class="metismenu" id="menu">%s</ul>', $html);
        } else {
            return sprintf('<ul class="collapse">%s</ul>', $html);
        }
    }

    protected function isSuperAdministor()
    {
        return !$this->cachedRoles()->where('slug', 'SuperAdministor')->isEmpty();
    }
    
    /**
     * 判断用户是否拥有指定角色
     *
     * @param  string|array $slug
     * @param  bool $requiredAll
     * @return bool
     *
     * 示例：
     *  $user->hasRole('user'); # true
     *  $user->hasRole('Agent'); # false
     *  $user->hasRole(['user', 'Agent']); # true
     *  $user->hasRole(['user', 'Agent'], true); # false
     */
    public function hasRole($slug, $requiredAll = false)
    {
        if (is_array($slug)) {
            foreach ($slug as $roleSlug) {
                $hasRole = $this->hasRole($roleSlug);

                if (!$requiredAll && $hasRole) {
                    return true;
                } elseif ($requiredAll && !$hasRole) {
                    return false;
                }
            }

            return $requiredAll;
        } else {
            foreach ($this->roles()->get() as $role) {
                if ($role->slug == $slug) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * 解除当前用户的锁定状态
     * 
     * @return [type] [description]
     */
    public function unlock(){
        $this->make_mistake = 0;
        $this->save();
    }
    /**
     * 创建并保存一个投资人用户
     * 
     * @param  array  $args [description]
     * @return [type]       [description]
     */
    public static function saveFront(array $args){

        DB::transaction(function() use ($args){


            $user = new User($args);
            $user->scope = 'front';
            $user->password = bcrypt(md5($args['password']));
            $user->identity_id = static::createIdentityId();
            $user->save();

            $userInfo = new UserInfo($args);
            $userInfo->invite_code = static::createInviteCode();
            $userInfo->user_id = $user->id;
            $userInfo->recommended = null;
            $userInfo->org_code = config('p2pdefault.user.organizational_code');
            $userInfo->dept_code = config('p2pdefault.user.dept_code');
            $userInfo->broker_code = config('p2pdefault.user.broker_code');

            if (!empty(@$args['recommended'])) {
                if ($broker_user = UserInfo::where('invite_code', '=', $args['recommended'])->first()) {
                    if($broker_user->user->hasRole('Agent')){   //推荐人是经纪人
                        //保存经纪人code
                        $userInfo->broker_code = $broker_user->invite_code;
                        $userInfo->org_code = $broker_user->org_code;
                        $userInfo->dept_code = $broker_user->dept_code;
                    }else{//保存推荐人ID
                        $userInfo->recommended = $broker_user->user_id;
                    }
                } else {
                    abort(600,'推荐人不存在');
                }
            }

            $userInfo->save();

            if(!$role = Role::where('slug', 'User')->first()){
                abort(600, '投资人角色不存在');
            }
            //保存用户角色
            $user->roles()->attach($role->id);

            //激活sina会员
            $result = $user->createActivateMember();

            if ($result['response_code'] != 'APPLY_SUCCESS') {
                abort(600, $result['response_message']);
            }

        });
    }

    /**
     * 创建用户sina会员id
     * @return [type]
     */
    protected static function createIdentityId(){
           //生成sinaUID
        do{
            $identity_id = createSinaIdentityId();

        }while(User::where('identity_id', $identity_id)->exists());

        return $identity_id;
    }

    /**
     * 创建用户推荐码
     * @return [type]
     */
    protected static function createInviteCode(){
        do{
            //为用户创建推荐码
            $invite_code = create_code(6);

        }while(UserInfo::where('invite_code', $invite_code)->exists());

        return $invite_code;
    }

    /**
     * 激活sina会员
     * @return [type]
     */
    protected function createActivateMember(){
        return CreateActivateMember::send(['identity_id' => $this->identity_id, 'identity_type' => 'UID']);
    }
    /**
     * 查询用户是否设置支付密码
     * @return boolean [description]
     */
    public function isSetPayPassword(){
        if($this->userInfo->is_set_pay_password == 1){
            return true;
        }else{
            //向sina发起请求,查询当前用户是否设置支付密码
            $result = QueryIsSetPayPassword::send(['identity_id' => $this->identity_id, 'identity_type' => 'UID']);
            if($result['response_code'] != 'APPLY_SUCCESS'){
                abort(600,$result['response_message']);
            }
            if($result['is_set_paypass'] == 'Y'){
                return true;
            }else{
                return false;
            }
        }
    }
}